#include "random_in.h"
#include <math.h>

typedef unsigned char BitSequence;
static int BytesToBitSequence(unsigned char* bytes_data, int in_len,
                       BitSequence* bits_data, int bits_data_len);

#define SAMPLE_BITS_LEN 1024
#define SAMPLE_BYTES_LEN (SAMPLE_BITS_LEN/8)

/**
 * @brief 重复计数测试
 * 
 * @return int 成功返回0，或错误码
 */
int _recount_test()
{
    int ret = 0;
    double c = ceil(20/2) + 1;
    unsigned char bits_data[SAMPLE_BITS_LEN];
    unsigned char random[SAMPLE_BYTES_LEN];

    ret = linx_random(random, SAMPLE_BYTES_LEN);
    if(ret) return ret;

    ret =  BytesToBitSequence(random, SAMPLE_BYTES_LEN, bits_data, SAMPLE_BITS_LEN);
    if(ret) return ret;

    char A = bits_data[0];
    int b = 1;
    for (int i = 1; i < SAMPLE_BITS_LEN; i++)
    {
        char x = bits_data[i];
        if(x == A){
            ++b;
            if(b >= c) {
                return 999;
            }
        } else {
            A = x;
            b = 1;
        }
    }
    return 0;
}

/**
 * @brief 自适应比例测试
 * 
 * @return int 成功返回0，或错误码
 */
int _adaptive_scale_test()
{
    int ret = 0;
    double c = 589;
    unsigned char bits_data[SAMPLE_BITS_LEN];
    unsigned char random[SAMPLE_BYTES_LEN];

    ret = linx_random(random, SAMPLE_BYTES_LEN);
    if(ret) return ret;

    ret =  BytesToBitSequence(random, SAMPLE_BYTES_LEN, bits_data, SAMPLE_BITS_LEN);
    if(ret) return ret;

    for (int i = 0; i < SAMPLE_BITS_LEN; i++) {
        char A = bits_data[i];
        int b = 1;
        for (int j = i+1; j < SAMPLE_BITS_LEN; j++) {
            if(A == bits_data[j]) ++b;

            if(b >= c) return 9999;
        }
    }
    return 0;
}

static unsigned char _compute(unsigned char b, unsigned char factor)
{
    if ((factor & b) == factor) {
        return 0x01;
    } else {
        return 0x00;
    }
}

static int BytesToBitSequence(unsigned char* bytes_data, int in_len,
                       BitSequence* bits_data, int bits_data_len)
{
    int j = 0, i = 0;
    if (bits_data_len < in_len * 8) {
        return -(__LINE__);
    }

    for (i = 0; i < in_len; ++i) {
        j                = i * 8;
        bits_data[j + 0] = (BitSequence)(_compute(bytes_data[i], 0x80));
        bits_data[j + 1] = (BitSequence)(_compute(bytes_data[i], 0x40));
        bits_data[j + 2] = (BitSequence)(_compute(bytes_data[i], 0x20));
        bits_data[j + 3] = (BitSequence)(_compute(bytes_data[i], 0x10));
        bits_data[j + 4] = (BitSequence)(_compute(bytes_data[i], 0x08));
        bits_data[j + 5] = (BitSequence)(_compute(bytes_data[i], 0x04));
        bits_data[j + 6] = (BitSequence)(_compute(bytes_data[i], 0x02));
        bits_data[j + 7] = (BitSequence)(_compute(bytes_data[i], 0x01));
    }
    return 0;
}